!--------------------------------
! Programa dedicado a calcular
! As (N+1)! permutacoes de N+1 elementos
! no arquivo perm_out.dat dadas as
! N! permutacoes de N elementos
!
! Programa compilado e testado com:
! $ gfortran -o exec03 exec03.f90
! $ ./exec03
! 
! Forma de utilizacao auto-explicativa
! atravez de comentarios.
!
! _o_o_ oOo _o_o_ 15/09/2010

PROGRAM exec03
  IMPLICIT NONE

  INTERFACE 
    FUNCTION Factorial(n)
      INTEGER :: Factorial
      INTEGER, INTENT(IN) :: n
    END FUNCTION Factorial
  END INTERFACE

  INTEGER, DIMENSION(10000,7) :: perms_old ! As permutacoes antigas
  INTEGER, DIMENSION(10000,8) :: perms_new ! As novas permutacoes
  INTEGER :: N, i, j, apont, fact ! Numero de elementos, iterador

  write(*,*) "quantos elementos voce vai ler do arquivo? (N)"
  read(*,*) N
  fact = Factorial(N)
!   write(*,*) fact

  write(*,*) "Lendo as permutacoes do arquivo perm_in.dat."
  OPEN(11,file='perm_in.dat')
  i=1
  DO WHILE (i<=fact)
      read(11,*) perms_old(i,1:N+1)
!       write (*,*) i, "ok"
      i=i+1
  END DO

  !!!!!!!!!!!!!!!!!!!!!!!!!!
!   write(*,*) "Verificacao"
!   i=1
!   DO WHILE (i<=fact)
!       write(*,*) "linha, ", i
!       j=1
!       DO WHILE (j<=N+1)
!             write(*,*) perms_old(i,j)
!             j = j+1
!       END DO
!       i=i+1
!   END DO
  !!!!!!!!!!!!!!!!!!!!!!!!!!

  open(unit=10,file="perm_out.dat")

  write(*,*) "Fazendo novas permutacoes"
  i=1
  DO WHILE (i<=fact)
      apont=1+(i-1)*(N+1)
!       write(*,*) i, apont
      perms_new(apont,1:N)=perms_old(i,1:N)
      perms_new(apont,N+1)=N+1
      perms_new(apont,N+2)=perms_old(i,N+1)
!       write(*,*) perms_new(apont,1:N+2)
      write(10,*) perms_new(apont,1:N+2)
      j=2
      DO WHILE (j<=N+1)
            perms_new(apont+j-1,1:N)=perms_old(i,1:N) ! copia permutacao
!             write(*,*) "ok1", perms_new(apont+j-1,1:N)
            perms_new(apont+j-1,N+1-(j-1))=N+1 ! coloca elemento extra
!             write(*,*) "ok2", perms_new(apont+j-1,1:N+1)
            perms_new(apont+j-1,N+1)=perms_old(i,N+1-(j-1)) !recoloca
!             write(*,*) "ok3", perms_new(apont+j-1,1:N+1)
            perms_new(apont+j-1,N+2)=perms_old(i,N+1)*(-1) ! copia paridade
!             write(*,*) perms_new(apont+j-1,1:N+2)
            write(10,*) perms_new(apont+j-1,1:N+2)
            j=j+1
      END DO
      i=i+1
  END DO

end PROGRAM

!-----Factorial------------------------------------------------------
!
!  Function to calculate factorials resursively
!
!---------------------------------------------------------------------
RECURSIVE FUNCTION Factorial(n)  RESULT(Fact)

IMPLICIT NONE
INTEGER :: Fact
INTEGER, INTENT(IN) :: n

  IF (n == 0) THEN
    Fact = 1
  ELSE
    Fact = n * Factorial(n-1)
  END IF

END FUNCTION Factorial
